package com.chatplus.application.xxljob;

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackageClasses = XxlJobAutoConfiguration.class)
public class XxlJobAutoConfiguration {

    public static final String XXL_JOB_CONFIG_KEY_ROOTS = "xxl.job";

    @Bean
    @ConfigurationProperties(XXL_JOB_CONFIG_KEY_ROOTS)
    @ConditionalOnProperty(prefix = XXL_JOB_CONFIG_KEY_ROOTS, name = "admin.addresses")
    public XxlJobProperties xxlJobProperties() {
        return new XxlJobProperties();
    }

    @Bean
    @ConditionalOnBean(XxlJobProperties.class)
    public XxlJobSpringExecutor xxlJobExecutor(XxlJobProperties xxlJobProperties) {

        XxlJobProperties.Admin admin = xxlJobProperties.getAdmin();
        XxlJobProperties.Executor executor = xxlJobProperties.getExecutor();

        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAccessToken(xxlJobProperties.getAccessToken());
        xxlJobSpringExecutor.setAdminAddresses(admin.getAddresses());
        xxlJobSpringExecutor.setAppname(executor.getAppname());
        xxlJobSpringExecutor.setAddress(executor.getAddress());
        xxlJobSpringExecutor.setIp(executor.getIp());
        xxlJobSpringExecutor.setPort(executor.getPort());
        xxlJobSpringExecutor.setLogPath(executor.getLogPath());
        xxlJobSpringExecutor.setLogRetentionDays(executor.getLogRetentionDays());

        return xxlJobSpringExecutor;
    }

    /**
     * 针对多网卡、容器内部署等情况，可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP；
     * <p>
     * 1、引入依赖：
     * <dependency>
     * <groupId>org.springframework.cloud</groupId>
     * <artifactId>spring-cloud-commons</artifactId>
     * <version>${version}</version>
     * </dependency>
     * <p>
     * 2、配置文件，或者容器启动变量
     * spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
     * <p>
     * 3、获取IP
     * String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
     */

    public static class XxlJobProperties {
        //执行器通讯TOKEN [选填]：非空时启用；非空时调度中心需要配置一致，方能正常通信
        private String accessToken;
        private Admin admin;
        private Executor executor;

        public static class Admin {
            //调度中心url
            private String addresses;

            public String getAddresses() {
                return addresses;
            }

            public void setAddresses(String addresses) {
                this.addresses = addresses;
            }
        }

        //执行器配置
        public static class Executor {

            //执行器AppName [选填]：执行器心跳注册分组依据；为空则关闭自动注册
            private String appname;

            //执行器注册 [选填]：优先使用该配置作为注册地址，为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
            private String address;

            //执行器IP [选填]：默认为空表示自动获取IP，多网卡时可手动设置指定IP，该IP不会绑定Host仅作为通讯实用；地址信息用于 "执行器注册" 和 "调度中心请求并触发任务"；
            private String ip;

            //执行器端口号 [选填]：小于等于0则自动获取；默认端口为9999，单机部署多个执行器时，注意要配置不同执行器端口；
            private int port;

            //执行器运行日志文件存储磁盘路径 [选填] ：需要对该路径拥有读写权限；为空则使用默认路径；
            private String logPath = "/data/applogs/xxl-job/jobhandler";

            //执行器日志文件保存天数 [选填] ： 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能；
            private int logRetentionDays = 30;

            public String getAppname() {
                return appname;
            }

            public void setAppname(String appname) {
                this.appname = appname;
            }

            public String getAddress() {
                return address;
            }

            public void setAddress(String address) {
                this.address = address;
            }

            public String getIp() {
                return ip;
            }

            public void setIp(String ip) {
                this.ip = ip;
            }

            public int getPort() {
                return port;
            }

            public void setPort(int port) {
                this.port = port;
            }

            public String getLogPath() {
                return logPath;
            }

            public void setLogPath(String logPath) {
                this.logPath = logPath;
            }

            public int getLogRetentionDays() {
                return logRetentionDays;
            }

            public void setLogRetentionDays(int logRetentionDays) {
                this.logRetentionDays = logRetentionDays;
            }
        }

        public String getAccessToken() {
            return accessToken;
        }

        public void setAccessToken(String accessToken) {
            this.accessToken = accessToken;
        }

        public Admin getAdmin() {
            return admin;
        }

        public void setAdmin(Admin admin) {
            this.admin = admin;
        }

        public Executor getExecutor() {
            return executor;
        }

        public void setExecutor(Executor executor) {
            this.executor = executor;
        }
    }

}
